﻿//////////////////////////////////////////////////////////////////////////////
//
// Copyright © 1998-2024 Glodon Company Limited.
//
// Licensed under the MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the “Software”),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//////////////////////////////////////////////////////////////////////////////
#include "QtRadioButtonGroup.h"
#include "GbmpNew.h"
#include "RadioButtonGroupDefinition.h"
#include <QRadioButton>
#include "IControlDefinitionChangeEventArgs.h"
#include "ControlDefinitionChangeEvent.h"
#include "QLayout.h"
#include <QVariant>
#include "UiQtUtil.h"
#include "ControlDefinitionUtil.h"
#include "EnableCompileWarning_The_LAST_IncludeInCpp.h"

using namespace gcmp;

QtRadioButtonGroup::QtRadioButtonGroup(OwnerPtr<IRadioButtonGroupDefinition> pControlDefinition, QWidget* pParent)
    : QButtonGroup(pParent)
    , m_pControlDefinition(TransferOwnership(pControlDefinition))
    , m_pParent(pParent)
{
    if (!m_pControlDefinition || !pParent)
    {
        DBG_WARN(L"m_pControlDefinition或pParent是空指针",L"GDMPLab",L"2024-03-30");
        return;
    }

    setExclusive(true);
    setProperty(IS_DEFINITION, true);
    const std::wstring currentButtonId = m_pControlDefinition->GetCurrentRadioButton();
    std::vector<const IRadioButtonDefinition*> checkBoxDefines = m_pControlDefinition->GetAllRadioButtons();
    for (auto define : checkBoxDefines)
    {
        AddRadioButton(define);
    }

    connect<void(QButtonGroup::*)(QAbstractButton*)>(this, &QButtonGroup::buttonClicked, this, &QtRadioButtonGroup::OnButtonClicked);
    IControlDefinitionChangeEvent* pControlDefinitionChangeEvent = ControlDefinitionUtil::GetControlDefinitionChangeEvent(m_pControlDefinition.get());
    if (pControlDefinitionChangeEvent)
    {
        pControlDefinitionChangeEvent->Add(this);
    }
}

QtRadioButtonGroup::~QtRadioButtonGroup()
{
    IControlDefinitionChangeEvent* pControlDefinitionChangeEvent = ControlDefinitionUtil::GetControlDefinitionChangeEvent(m_pControlDefinition.get());
    if (pControlDefinitionChangeEvent)
    {
        pControlDefinitionChangeEvent->Delete(this);
    }
}

IControlDefinition* QtRadioButtonGroup::GetControlDefinition() const
{
    return const_cast<IRadioButtonGroupDefinition*>(m_pControlDefinition.get());
}

std::vector<QRadioButton*> QtRadioButtonGroup::GetAllControls() const
{
    return m_radioButtonControls;
}

void QtRadioButtonGroup::OnButtonClicked(QAbstractButton* pButton)
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(m_pControlDefinition, L"pControlDefinition为空",L"GDMPLab",L"2024-03-30");
    QRadioButton* pRadioButton = qobject_cast<QRadioButton*>(pButton);
    DBG_WARN_AND_RETURN_VOID_UNLESS(pRadioButton, L"pCheckBox为空",L"GDMPLab",L"2024-03-30");

    RadioButtonGroupStateChangeFlag flag(true);

    std::wstring id = pRadioButton->objectName().toStdWString();
    {
        ControlDefinitionChangeByUser changeByUser(m_pControlDefinition->GetId());
        m_pControlDefinition->SetCurrentRadioButton(id);
    }
    
    
}

void gcmp::QtRadioButtonGroup::On(IControlDefinitionChangeEventArgs* pArgs)
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(pArgs, L"pArgs为空",L"GDMPLab",L"2024-03-30");
    if (pArgs->GetType() == ControlDefinitionChangeEventType::Add)
    {
        OnControlDefinitionChangeEventTypeAdd(pArgs);
    }
    else if (pArgs->GetType() == ControlDefinitionChangeEventType::Insert)
    {
        OnControlDefinitionChangeEventTypeInsert(pArgs);
    }
    else if (pArgs->GetType() == ControlDefinitionChangeEventType::Delete)
    {
        int deleteControlDefinitionIndex = pArgs->GetDeleteOrInsertControlDefinitionIndex();
        DBG_WARN_AND_RETURN_VOID_UNLESS(deleteControlDefinitionIndex >= 0 && deleteControlDefinitionIndex < m_radioButtonControls.size(), L"deleteControlDefinitionIndex有误",L"GDMPLab",L"2024-03-30");
        DBG_WARN_AND_RETURN_VOID_UNLESS(m_radioButtonControls[deleteControlDefinitionIndex], L"iter为空",L"GDMPLab",L"2024-03-30");
        removeButton(m_radioButtonControls[deleteControlDefinitionIndex]);

        m_radioButtonControls[deleteControlDefinitionIndex]->deleteLater();

        auto indexDeleteIter = m_radioButtonControls.begin();
        std::advance(indexDeleteIter, deleteControlDefinitionIndex);
        m_radioButtonControls.erase(indexDeleteIter);
    }
    else if (pArgs->GetType() == ControlDefinitionChangeEventType::DeleteAll)
    {
        for (auto iter : m_radioButtonControls)
        {
            DBG_WARN_AND_CONTINUE_UNLESS(iter, L"iter为空",L"GDMPLab",L"2024-03-30");
            removeButton(iter);
            iter->deleteLater();
        }
        m_radioButtonControls.clear();
    }
    
    else if (pArgs->GetType() == ControlDefinitionChangeEventType::Other)
    {
        std::vector<QRadioButton*> radioButtonControls = GetAllControls();
        std::vector<const IRadioButtonDefinition*> radioButtonGroupDefinition = m_pControlDefinition->GetAllRadioButtons();
        DBG_WARN_AND_RETURN_VOID_UNLESS(radioButtonControls.size() == radioButtonGroupDefinition.size(), L"数据有误",L"GDMPLab",L"2024-03-30");
        const std::wstring currentButtonId = m_pControlDefinition->GetCurrentRadioButton();
        for (int i = 0; i < (int)radioButtonControls.size(); ++i)
        {
            DBG_WARN_AND_CONTINUE_UNLESS(radioButtonGroupDefinition[i] && radioButtonControls[i], L"radioButtonGroupDefinition[i] && radioButtonControls[i]为空",L"GDMPLab",L"2024-03-30");
            DBG_WARN_AND_CONTINUE_UNLESS(radioButtonControls[i], L"pQRadioButton为空",L"GDMPLab",L"2024-03-30");
            if (radioButtonControls[i]->objectName().toStdWString() == currentButtonId && radioButtonControls[i]->isChecked() != true)
            {
                radioButtonControls[i]->setChecked(true);
            }
            if (radioButtonGroupDefinition[i]->IsVisible() != radioButtonControls[i]->isVisible())
            {
                radioButtonControls[i]->setVisible(radioButtonGroupDefinition[i]->IsVisible());
            }
            if (radioButtonGroupDefinition[i]->IsEnabled() != radioButtonControls[i]->isEnabled())
            {
                radioButtonControls[i]->setEnabled(radioButtonGroupDefinition[i]->IsEnabled());
            }
        }
    }
}

void gcmp::QtRadioButtonGroup::UpdateStatus()
{
    std::vector<QRadioButton*> radioButtonControls = this->GetAllControls();
    IRadioButtonGroupDefinition* pDefinition = dynamic_cast<IRadioButtonGroupDefinition*>(this->GetControlDefinition());
    DBG_WARN_AND_RETURN_VOID_UNLESS(pDefinition != nullptr, L"pDefinition为空",L"GDMPLab",L"2024-03-30");
    std::vector<const IRadioButtonDefinition*> radioButtonDefines = pDefinition->GetAllRadioButtons();
    DBG_WARN_AND_RETURN_VOID_UNLESS(radioButtonControls.size() == radioButtonDefines.size(), L"数据有误",L"GDMPLab",L"2024-03-30");
    for (int i = 0; i < (int)radioButtonDefines.size(); ++i)
    {
        DBG_WARN_AND_CONTINUE_UNLESS(radioButtonDefines[i] && radioButtonControls[i], L"radioButtonDefines[i] && radioButtonControls[i]为空",L"GDMPLab",L"2024-03-30");
        radioButtonControls[i]->setVisible(radioButtonDefines[i]->IsVisible());
        radioButtonControls[i]->setEnabled(radioButtonDefines[i]->IsEnabled());
    }
}

QRadioButton* gcmp::QtRadioButtonGroup::AddRadioButton(const IRadioButtonDefinition* pDefinition)
{
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pDefinition, L"pDefinition为空",L"GDMPLab",L"2024-03-30");
    QRadioButton* pRadioButton = CreateControl(pDefinition);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pRadioButton, L"pRadioButton为空",L"GDMPLab",L"2024-03-30");
    const std::wstring currentButtonId = m_pControlDefinition->GetCurrentRadioButton();

    if (pDefinition->GetId() == currentButtonId)
    {
        pRadioButton->setChecked(true);
    }

    addButton(pRadioButton);

    m_radioButtonControls.push_back(pRadioButton);
    return pRadioButton;
}

QRadioButton* gcmp::QtRadioButtonGroup::CreateControl(const IRadioButtonDefinition* pDefinition)
{
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(m_pParent, L"m_pParent为空",L"GDMPLab",L"2024-03-30");
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pDefinition, L"pDefinition为空",L"GDMPLab",L"2024-03-30");

    QRadioButton* pRadioButton = NEW_AS_QT(QRadioButton, QString::fromStdWString(pDefinition->GetCaption()), m_pParent);
    pRadioButton->setProperty(IS_DEFINITION, true);
    pRadioButton->setObjectName(QString::fromStdWString(pDefinition->GetId()));
    pRadioButton->setToolTip(QString::fromStdWString(pDefinition->GetTooltip()));
    pRadioButton->setVisible(pDefinition->IsVisible());
    pRadioButton->setEnabled(pDefinition->IsEnabled());
    return pRadioButton;
}

void gcmp::QtRadioButtonGroup::OnControlDefinitionChangeEventTypeInsert(IControlDefinitionChangeEventArgs* pArgs)
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(pArgs, L"pArgs为空",L"GDMPLab",L"2024-03-30");
    //1.移出QButtonGroup所有控件
    for (auto iter : m_radioButtonControls)
    {
        DBG_WARN_AND_CONTINUE_UNLESS(iter, L"iter为空",L"GDMPLab",L"2024-03-30");
        removeButton(iter);
    }
    //2.根据插入的define创建对应的控件
    const IRadioButtonDefinition* pDefinition = dynamic_cast<const IRadioButtonDefinition*>(pArgs->GetControlDefinition());
    DBG_WARN_AND_RETURN_VOID_UNLESS(pDefinition, L"pDefinition为空",L"GDMPLab",L"2024-03-30");
    QRadioButton* pRadioControl = CreateControl(pDefinition);
    DBG_WARN_AND_RETURN_VOID_UNLESS(pRadioControl, L"pRadioControl为空",L"GDMPLab",L"2024-03-30");

    int insertControlDefinitionIndex = pArgs->GetDeleteOrInsertControlDefinitionIndex();
    DBG_WARN_AND_RETURN_VOID_UNLESS(insertControlDefinitionIndex >= 0 && insertControlDefinitionIndex < m_radioButtonControls.size(), L"insertControlDefinitionIndex有误",L"GDMPLab",L"2024-03-30");

    //3.往m_parent插入对应的控件
    QLayout * pLayout = m_pParent->layout();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pLayout, L"pLayout为空",L"GDMPLab",L"2024-03-30");
    int index = pLayout->indexOf(m_radioButtonControls[insertControlDefinitionIndex]);
    QBoxLayout* pQBoxLayout = dynamic_cast<QBoxLayout*>(pLayout);
    DBG_WARN_AND_RETURN_VOID_UNLESS(pQBoxLayout, L"pQBoxLayout为空",L"GDMPLab",L"2024-03-30");
    pQBoxLayout->insertWidget(index, pRadioControl);

    //4.往m_radioButtonControls中插入对应的控件
    auto indexInsertIter = m_radioButtonControls.begin();
    std::advance(indexInsertIter, insertControlDefinitionIndex);
    m_radioButtonControls.insert(indexInsertIter, pRadioControl);

    //5.添加m_radioButtonControls所有控件到QButtonGroup
    for (auto iter : m_radioButtonControls)
    {
        DBG_WARN_AND_CONTINUE_UNLESS(iter, L"iter为空",L"GDMPLab",L"2024-03-30");
        addButton(iter);
    }
}

void gcmp::QtRadioButtonGroup::OnControlDefinitionChangeEventTypeAdd(IControlDefinitionChangeEventArgs* pArgs)
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(pArgs, L"pArgs为空",L"GDMPLab",L"2024-03-30");
    DBG_WARN_AND_RETURN_VOID_UNLESS(m_pParent, L"m_pParent为空",L"GDMPLab",L"2024-03-30");

    QLayout * pLayout = m_pParent->layout();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pLayout, L"pLayout为空",L"GDMPLab",L"2024-03-30");
    QRadioButton* pRadioButtonRef = m_radioButtonControls.back();
    int index = pLayout->indexOf(pRadioButtonRef);

    const IRadioButtonDefinition* pRadioButtonDefine = dynamic_cast<const IRadioButtonDefinition*>(pArgs->GetControlDefinition());
    DBG_WARN_AND_RETURN_VOID_UNLESS(pRadioButtonDefine, L"pCheckBoxDefine为空",L"GDMPLab",L"2024-03-30");
    QRadioButton* pControl = AddRadioButton(pRadioButtonDefine);
    DBG_WARN_AND_RETURN_VOID_UNLESS(pControl, L"pControl为空",L"GDMPLab",L"2024-03-30");

    QBoxLayout* pQBoxLayout = dynamic_cast<QBoxLayout*>(pLayout);
    DBG_WARN_AND_RETURN_VOID_UNLESS(pQBoxLayout, L"pQBoxLayout为空",L"GDMPLab",L"2024-03-30");

    pQBoxLayout->insertWidget(index + 1, pControl);
}
